import cv2
import numpy as np


img = cv2.imread('./lena.jpg')
h = np.zeros((256, 256, 3))  # 创建用于绘制直方图的全0图像
print('=========h========', h)
bins = np.arange(256).reshape(256, 1)  # 直方图中各bin的顶点位置
color = [(255, 0, 0), (0, 255, 0), (0, 0, 255)]  # BGR三种颜色
for ch, col in enumerate(color):
    print('=========ch========', ch)
    print('=========col========', col)
    '''
    #直方图x轴是灰度值（一般0~255），y轴就是图像中每一个灰度级对应的像素点的个数。
    那么如何获得图像的直方图？首先来了解绘制直方图需要的一些量：灰度级，正常情况下就是0 - 255
    共256个灰度级，从最黑一直到最亮（白）（也有可能统计其中的某部分灰度范围），那么每一个灰度级对应一个数来储存该灰度对应的点数目
    直方图均衡化的中心思想是把原始图像的的灰度直方图从比较集中的某个区域变成在全部灰度范围内的均匀分布。
    
    计算灰度直方图calcHist()，该函数有5个参数：
    image输入图像，传入时应该用中括号[]括起来
    channels:：传入图像的通道，如果是灰度图像，那就不用说了，只有一个通道，值为0，如果是彩色图像（有3个通道），
                那么值为0,1,2,中选择一个，对应着BGR各个通道。这个值也得用[]传入。
    mask：掩膜图像。如果统计整幅图，那么为none。主要是如果要统计部分图的直方图，就得构造相应的炎掩膜来计算。
    histSize：灰度级的个数，需要中括号，比如[256]
    ranges:像素值的范围，通常[0,256]，有的图像如果不是0-256，比如说你来回各种变换导致像素值负值、很大，则需要调整后才可以。
    '''
    originHist = cv2.calcHist([img], [ch], None, [256], [0, 256])
    '''
    功能：归一化函数
    src-输入数组。
    dst-与SRC大小相同的输出数组。
    α-范数值在范围归一化的情况下归一化到较低的范围边界。
    β-上限范围在范围归一化的情况下；它不用于范数归一化。

    范式-规范化类型
    dType——当输出为负时，输出数组具有与SRC相同的类型；否则，它具有与SRC相同的信道数和深度＝CVH-MatthAsHead（DyType）。
    面具-可选的操作面具。
    这个函数提供了四种归一化方式，可根据需要选择以下四个参数，下面重点说下这四种归一化方式。
    NORM_MINMAX:数组的数值被平移或缩放到一个指定的范围，线性归一化。
    NORM_INF: 归一化数组的（切比雪夫距离）L∞范数(绝对值的最大值)
    NORM_L1 :  归一化数组的（曼哈顿距离）L1-范数(绝对值的和)
    NORM_L2: 归一化数组的(欧几里德距离)L2-范数
    '''
    cv2.normalize(originHist, originHist, 0, 255 * 0.9, cv2.NORM_MINMAX)
    #int32()计算的像素个数转为32为整数数组
    #round() 方法返回浮点数x的四舍五入值。
    hist = np.int32(np.around(originHist))
    #按列放入数组顶点x位置y个数
    pts = np.column_stack((bins, hist))
    '''
    line() 绘制直线
    rectangle() 绘制矩形
    ellipse() 绘制椭圆
    polylines() 绘制多边形
    putText() 加入文字
    '''
    #绘制多边形
    cv2.polylines(h, [pts], False, col)
#flipud()矩阵上下翻转 fliplr()矩阵左右翻转
h = np.flipud(h)
cv2.imshow('img', img)
cv2.imshow('colorhist', h)
cv2.waitKey(0)
